/**
 * Baijiahulian.com Inc.
 * Copyright (c) 2014-2016 All Rights Reserved.
 */
package com.baijia.authentication.handler.support;

import com.baijia.authentication.handler.exception.AuthenticationException;
import com.baijia.authentication.handler.exception.UrlMessageException;
import com.baijia.authentication.principal.Credentials;
import com.baijia.authentication.principal.credentials.MobileCredentials;
import com.baijia.services.ServicesManager;
import com.baijia.services.impl.RegisteredServiceImpl;
import com.baijia.util.MobileLoginUtil;

import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

/**
 * @title UserAuthenticationHandler
 * @desc TODO 
 * @author macrohuang
 * @date Jan 20, 2016
 * @version 1.0
 */
@Component
public class MobileAuthenticationHandler extends AbstractPreAndPostProcessingAuthenticationHandler {

    @Autowired
    protected ServicesManager servicesManager;
    
    /* (non-Javadoc)
     * @see com.baijia.authentication.handler.support.AbstractPreAndPostProcessingAuthenticationHandler#preAuthenticate(com.baijia.authentication.principal.Credentials)
     */
    @Override
    protected boolean preAuthenticate(Credentials credentials) throws AuthenticationException {
        MobileCredentials mobileCredentials = (MobileCredentials) credentials;
        RegisteredServiceImpl service =
            (RegisteredServiceImpl) servicesManager.findServiceBy(mobileCredentials.getAccountType());
        
        if (MobileLoginUtil.isUserBlock(mobileCredentials.getUsername())){
            throw new UrlMessageException("banned", "账号已被锁定，请1小时后再试！");
        }else if (!MobileLoginUtil.canUserLogin(mobileCredentials.getUsername())){
            throw new UrlMessageException("banned","登录过于频繁，请1分钟后再试！");
        }else if (MobileLoginUtil.getUserRetries(mobileCredentials.getUsername())>service.getLoginMaxTimes()){
            throw new UrlMessageException("banned", "超过最大重试次数，用户将被禁止登录1小时！");
        }
        return true;
    }

    /* (non-Javadoc)
     * @see com.baijia.authentication.handler.support.AbstractPreAndPostProcessingAuthenticationHandler#postAuthenticate(com.baijia.authentication.principal.Credentials, boolean)
     */
    @Override
    protected boolean postAuthenticate(Credentials credentials, boolean authenticated) throws AuthenticationException {
        MobileCredentials mobileCredentials = (MobileCredentials) credentials;
        if (!authenticated) {
            MobileLoginUtil.incRetry(mobileCredentials.getUsername());
            int failTimes = MobileLoginUtil.getUserRetries(mobileCredentials.getUsername());
            RegisteredServiceImpl service =
                (RegisteredServiceImpl) servicesManager.findServiceBy(mobileCredentials.getAccountType());
            if (failTimes >= service.getLoginMaxTimes()) {
                MobileLoginUtil.blockUser(mobileCredentials.getUsername(), service.getBanSeconds());
                throw new UrlMessageException("banned", "账号已被锁定，请1小时后再试！");
            } else if (failTimes >= service.getLoginNoticeTimes()) {
                throw new UrlMessageException("badCredential", "手机号与验证码不符" + failTimes + "次，还剩"
                    + (service.getLoginMaxTimes() - failTimes) + "次");
            }else {
                throw new UrlMessageException("badCredential", "手机号与验证码不符！");
            }
        } else {
            MobileLoginUtil.delUserRetries(mobileCredentials.getUsername());
            MobileLoginUtil.delPasscode(mobileCredentials.getUsername());
        }
        return authenticated;
    }

    /* (non-Javadoc)
     * @see com.baijia.authentication.handler.AuthenticationHandler#supports(com.baijia.authentication.principal.Credentials)
     */
    @Override
    public boolean supports(Credentials credentials) {
        return credentials instanceof MobileCredentials;
    }

    /* (non-Javadoc)
     * @see com.baijia.authentication.handler.support.AbstractPreAndPostProcessingAuthenticationHandler#doAuthentication(com.baijia.authentication.principal.Credentials)
     */
    @Override
    protected boolean doAuthentication(Credentials credentials) throws AuthenticationException {
        MobileCredentials userCredentials = (MobileCredentials) credentials;
        String mobile = userCredentials.getUsername();
        String passcode = userCredentials.getPasscode();
        if (StringUtils.isBlank(mobile) || StringUtils.isBlank(passcode)){
            return false;
        }
        return testLogin(passcode) || MobileLoginUtil.validPasscode(mobile, passcode);
    }
}
